#pragma once

#include "../../base/obj_pointer.h"
#include "../../base/list.h"
#include "mapper.h"

OPEN_JLIB_NS


struct Action : public Obj {

  virtual void start () = 0;
  virtual bool done () const = 0;
  virtual f32 update (f32 dt) = 0;

  Obj* getTarget () noexcept { return _target.ptr(); }
  void setTarget (Obj* obj) noexcept { _target = obj; }

protected:
  Ptr<Obj> _target;
};


struct ImmediateAction : public Action {

  virtual void apply () = 0;

  void start () override;
  bool done () const override;
  f32 update (f32 dt) override;

protected:
  bool _updated;
};


struct ContinuedAction : public Action {

  typedef std::function<f32(f32)> mapper_t;

  virtual void apply (f32 progress) = 0;

  void start () override;
  bool done () const override;
  f32 update (f32 dt) override;

  bool init (f32 duration);

  void setMapper (std::function<f32(f32)> mapper) noexcept { _mapper = std::move(mapper); }
  f32 elapsed () const noexcept { return _elapsed; }
  f32 duration () const noexcept { return _duration; }

protected:
  mapper_t _mapper;
  f32 _elapsed;
  f32 _duration;
};


struct SeriesAction : public Action {

  void start () override;
  bool done () const override;
  f32 update (f32 dt) override;

  bool init (Action* a, ...);
  bool init (const std::vector<Ptr<Action>>& actions);

protected:
  std::vector<Ptr<Action>> _queue;
  u32 _init;
  u32 _done;
};


struct ParallelAction : public Action {

  void start () override;
  bool done () const override;
  f32 update (f32 dt) override;

  bool init (Action* a, ...);
  bool init (const std::vector<Ptr<Action>>& actions);

protected:
  std::vector<Ptr<Action>> _queue;
  u32 _done;
};


struct RepeatAction : public Action {

  void start () override;
  bool done () const override;
  f32 update (f32 dt) override;

  bool init (Action* action, s32 times);

protected:
  Ptr<Action> _action;
  u32 _loops;
  u32 _round;

};


CLOSE_JLIB_NS
